home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ASM_TUTR.ZIP / ASMTUTR3.DOC < prev    next >
Text File  |  1984-11-27  |  21KB  |  372 lines

  1.  
  2.  
  3.   PROGPREF SEGMENT   AT 0      ;Really a DSECT mapping the program prefix
  4.            ORG   PROGPREF+6
  5.   MEMSIZE  DW   ?              ;Size of available memory
  6.   PROGPREF ENDS
  7. Really, no matter whether the AT value represents truth or fiction, it is
  8. your responsibility, not the assembler's, to get set up a segment register
  9. so that you can really reach the storage in question.   So, you can't say
  10.          MOV  AL,EQUIP
  11. unless you first say something like
  12.          MOV  AX,BIOSAREA   ;BIOSAREA becomes a symbol with value 40H
  13.          MOV  ES,AX
  14.          ASSUME ES:BIOSAREA
  15. Enough about SEGMENT.  The END statement is simple.  It goes at the end of
  16. every assembly.  When you are assembling a subroutine, you just say
  17.          END
  18. but when you are assembling the main routine of a program you say
  19.         END label
  20. where 'label' is the place where execution is to begin.
  21. Another pseudo-op illustrated in the program is ASSUME.  ASSUME is like the
  22. USING statement in 370 assembler.  However, ASSUME can ONLY refer to seg-
  23. ment registers.  The assembler uses ASSUME information to decide whether to
  24. assemble segment override prefixes and to check that the data you are try-
  25. ing to access is really accessible.  In this case, we can reassure the
  26. assembler that both the CS and DS registers will address the section called
  27. HELLO at execution time.  Actually, the SS and ES registers will too, but
  28. the assembler never needs to make use of this information.
  29. I guess I have explained everything in the program except that ORG
  30. pseudo-op.  ORG means the same thing as it does in many assembly languages.
  31. It tells the assembler to move its location counter to some particular
  32. address.  In this case, we have asked the assembler to start assembling
  33. code hex 100 bytes from the start of the section called HELLO instead of at
  34. the very beginning.  This simply reflects the way COM programs are loaded.
  35. When a COM program is loaded by the system, the system sets up all four
  36. segment registers to address the same 64K of storage.  The first 100 hex
  37. bytes of that storage contains what is called the program prefix; this area
  38. is described in appendix E of the DOS manual.  Your COM program physically
  39. begins after this.  Execution begins with the first physical byte of your
  40. program; that is why the JMP instruction is there.
  41. Wait a minute, you say, why the JMP instruction at all?  Why not put the
  42. data at the end?  Well, in a simple program like this I probably could have
  43. gotten away with that.  However, I have the habit of putting data first and
  44. would encourage you to do the same because of the way the assembler has of
  45. assembling different instructions depending on the nature of the operand.
  46. IBM PC Assembly Language Tutorial                                        19
  47.  
  48.  
  49. Unfortunately, sometimes the different choices of instruction which can
  50. assemble from a single opcode have different lengths.  If the assembler has
  51. already seen the data when it gets to the instructions it has a good chance
  52. of reserving the right number of bytes on the first pass.  If the data is
  53. at the end, the assembler may not have enough information on the first pass
  54. to reserve the right number of bytes for the instruction.  Sometimes the
  55. assembler will complain about this, something like "Forward reference is
  56. illegal" but at other times, it will make some default assumption.  On the
  57. second pass, if the assumption turned out to be wrong, it will report what
  58. is called a "Phase error," a very nasty error to track down.  So get in the
  59. habit of putting data and equated symbols ahead of code.
  60. OK.  Maybe you understand the program now.  Let's walk through the steps
  61. involved in making it into a real COM file.
  62. 1.  The file should be created with the name HELLO.ASM (actually the name
  63.     is arbitrary but the extension .ASM is conventional and useful)
  64. 2.
  65.       ASM   HELLO,,;
  66.     (this is just one example of invoking the assembler; it uses the small
  67.     assembler ASM, it produces an object file and a listing file with the
  68.     same name as the source file.  I am not going exhaustively into how to
  69.     invoke the assembler, which the manual goes into pretty well.  I guess
  70.     this is the first time I mentioned that there are really two
  71.     assemblers; the small assembler ASM will run in a 64K machine and
  72.     doesn't support macros.  I used to use it all the time; now that I have
  73.     a bigger machine and a lot of macro libraries I use the full function
  74.     assembler MASM.  You get both when you buy the package).
  75. 3.  If you issue DIR at this point, you will discover that you have
  76.     acquired HELLO.OBJ (the object code resulting from the assembly) and
  77.     HELLO.LST (a listing file).  I guess I can digress for a second here
  78.     concerning the listing file.  It contains TAB characters.  I have found
  79.     there are two good ways to get it printed and one bad way.  The bad way
  80.     is to use LPT1: as the direct target of the listing file or to try
  81.     copying the LST file to LPT1 without first setting the tabs on the
  82.     printer.  The two good ways are to either
  83.     a.  direct it to the console and activate the printer with CTRL-PRTSC.
  84.         In this case, DOS will expand the tabs for you.
  85.     b.  direct to LPT1: but first send the right escape sequence to LPT1 to
  86.         set the tabs every eight columns.  I have found that on some early
  87.         serial numbers of the IBM PC printer, tabs don't work quite right,
  88.         which forces you to the first option.
  89. 4.
  90.           LINK  HELLO;
  91.     (again, there are lots of linker options but this is the simplest.  It
  92.     takes HELLO.OBJ and makes HELLO.EXE).  HELLO.EXE?  I thought we were
  93. IBM PC Assembly Language Tutorial                                        20
  94.  
  95.  
  96.     making a COM program, not an EXE program.  Right.  HELLO.EXE isn't
  97.     really executable; its just that the linker doesn't know about COM pro-
  98.     grams.  That requires another utility.  You don't have this utility if
  99.     you are using DOS 1.0; you have it if you are using DOS 1.1 or DOS 2.0.
  100.     Oh, by the way, the linker will warn you that you have no stack
  101.     segment.  Don't worry about it.
  102. 5.
  103.           EXE2BIN  HELLO HELLO.COM
  104.     This is the final step.  It produces the actual program you will exe-
  105.     cute.  Note that you have to spell out HELLO.COM; for a nominally
  106.     rational but actually perverse reason, EXE2BIN uses the default exten-
  107.     sion BIN instead of COM for its output file.  At this point, you might
  108.     want to erase HELLO.EXE; it looks a lot more useful than it is.
  109.     Chances are you won't need to recreate HELLO.COM unless you change the
  110.     source and then you are going to have to redo the whole thing.
  111. 6.
  112.           HELLO
  113.     You type hello, that invokes the program, it says
  114.           HELLO YOURSELF!!!
  115.     (oops, what did I do wrong....?)
  116.  
  117. What about subroutines?
  118. _______________________
  119. What about subroutines?
  120. What about subroutines?
  121. What about subroutines?
  122. I started with a simple COM program because I actually think they are easi-
  123. er to create than subroutines to be called from high level languages, but
  124. maybe its really the latter you are interested in.  Here, I think you
  125. should get comfortable with the assembler FIRST with little exercises like
  126. the one above and also another one which I will finish up with.
  127. Next you are ready to look at the interface information for your particular
  128. language.  You usually find this in some sort of an appendix.  For example,
  129. the BASIC manual has Appendix C on Machine Language Subroutines.  The
  130. PASCAL manual buries the information a little more deeply:  the interface
  131. to a separately compiled routine can be found in the Chapter on Procedures
  132. and Functions, in a subsection called Internal Calling Conventions.
  133. Each language is slightly different, but here are what I think are some
  134. common issues in subroutine construction.
  135. 1.  NEAR versus FAR?  Most of the time, your language will probably call
  136.     your assembler routine as a FAR routine.  In this case, you need to
  137.     make sure the assembler will generate the right kind of return.  You do
  138.     this with a PROC...ENDP statement pair.  The PROC statement is probably
  139.  
  140. IBM PC Assembly Language Tutorial                                        21
  141.  
  142.  
  143.     a good idea for a NEAR routine too even though it is not strictly
  144.     required:
  145.               FAR linkage:        |            NEAR linkage:
  146.                                   |
  147.     ARBITRARY SEGMENT             |  SPECIFIC  SEGMENT  PUBLIC
  148.               PUBLIC THENAME      |            PUBLIC THENAME
  149.               ASSUME CS:ARBITRARY |            ASSUME CS:SPECIFIC,DS:SPECIFIC
  150.     THENAME   PROC FAR            |            ASSUME ES:SPECIFIC,SS:SPECIFIC
  151.               ..... code and data |  THENAME   PROC NEAR
  152.     THENAME   ENDP                |            ..... code and data ....
  153.     ARBITRARY ENDS                |  THENAME   ENDP
  154.               END                 |  SPECIFIC  ENDS
  155.                                   |            END
  156.     With FAR linkage, it doesn't really matter what you call the segment.
  157.     you must declare the name by which you will be called in a PUBLIC pseu-
  158.     do-op and also show that it is a FAR procedure.  Only CS will be ini-
  159.     tialized to your segment when you are called.  Generally, the other
  160.     segment registers will continue to point to the caller's segments.
  161.     With NEAR linkage, you are executing in the same segment as the caller.
  162.     Therefore, you must give the segment a specific name as instructed by
  163.     the language manual.  However, you may be able to count on all segment
  164.     registers pointing to your own segment (sometimes the situation can be
  165.     more complicated but I cannot really go into all of the details).  You
  166.     should be aware that the code you write will not be the only thing in
  167.     the segment and will be physically relocated within the segment by the
  168.     linker.  However, all OFFSET references will be relocated and will be
  169.     correct at execution time.
  170. 2.  Parameters passed on the stack.  Usually, high level languages pass
  171.     parameters to subroutines by pushing words onto the stack prior to
  172.     calling you.  What may differ from language to language is the nature
  173.     of what is pushed (OFFSET only or OFFSET and SEGMENT) and the order in
  174.     which it is pushed (left to right, right to left within the CALL state-
  175.     ment).  However, you will need to study the examples to figure out how
  176.     to retrieve the parameters from the stack.  A useful fact to exploit is
  177.     the fact that a reference involving the BP register defaults to a ref-
  178.     erence to the stack segment.  So, the following strategy can work:
  179.       ARGS     STRUC
  180.                DW   3 DUP(?)  ;Saved BP and return address
  181.       ARG3     DW   ?
  182.       ARG2     DW   ?
  183.       ARG1     DW   ?
  184.       ARGS     ENDS
  185.            ...........
  186.                PUSH BP                 ;save BP register
  187.                MOV  BP,SP              ;Use BP to address stack
  188.                MOV   ...,[BP].ARG2     ;retrieve second argument
  189.                (etc.)
  190.  
  191. IBM PC Assembly Language Tutorial                                        22
  192.  
  193.  
  194.     This example uses something called a structure, which is only available
  195.     in the large assembler; furthermore, it uses it without allocating it,
  196.     which is not a well-documented option.  However, I find the above
  197.     approach generally pleasing.  The STRUC is like a DSECT in that it
  198.     establishes labels as being offset a certain distance from an arbitrary
  199.     point; these labels are then used in the body of code by beginning them
  200.     with a period; the construction ".ARG2" means, basically, " +
  201.     (ARG2-ARGS)."
  202.     What you are doing here is using BP to address the stack, accounting
  203.     for the word where you saved the caller's BP and also for the two words
  204.     which were pushed by the CALL instruction.
  205. 3.  How big is the stack?  BASIC only gives you an eight word stack to play
  206.     with.  On the other hand, it doesn't require you to save any registers
  207.     except the segment registers.  Other languages give you a liberal
  208.     stack, which makes things a lot easier.  If you have to create a new
  209.     stack segment for yourself, the easiest thing is to place the stack at
  210.     the end of your program and:
  211.          CLI                      ;suppress interrupts while changing the stack
  212.          MOV  SSAVE,SS            ;save old SS in local storage (old SP
  213.                                   ; already saved in BP)
  214.          MOV  SP,CS               ;switch
  215.          MOV  SS,SP               ;the
  216.          MOV  SP,OFFSET STACKTOP  ;stack
  217.          STI                      ;(maybe)
  218.     Later, you can reverse these steps before returning to the caller.  At
  219.     the end of your program, you place the stack itself:
  220.              DW   128 DUP(?)          ;stack of 128 words (liberal)
  221.     STACKTOP LABEL WORD
  222. 4.  Make sure you save and restore those registers required by the caller.
  223. 5.  Be sure to get the right kind of addressibility.  In the FAR call exam-
  224.     ple, only CS addresses your segment.  If you are careful with your
  225.     ASSUME statements the assembler will keep track of this fact and gener-
  226.     ate CS prefixes when you make data references; however, you might want
  227.     to do something like
  228.                     MOV AX,CS      ;get current segment address
  229.                     MOV DS,AX      ;To DS
  230.                     ASSUME DS:THISSEG
  231.     Be sure you keep your ASSUMEs in synch with reality.
  232.  
  233.  
  234.  
  235. IBM PC Assembly Language Tutorial                                        23
  236.  
  237.  
  238. Learning about BIOS and the hardware
  239. ____________________________________
  240. Learning about BIOS and the hardware
  241. Learning about BIOS and the hardware
  242. Learning about BIOS and the hardware
  243. You can't do everything with DOS calls.  You may need to learn something
  244. about the BIOS and about the hardware itself.  In this, the Technical Ref-
  245. erence is a very good thing to look at.
  246. The first thing you look at in the Technical Reference, unless you are
  247. really determined to master the whole ball of wax, is the BIOS listings
  248. presented in Appendix A. Glory be:  here is the whole 8K of ROM which deals
  249. with low level hardware support layed out with comments and everything.
  250. In fact, if you are just interested in learning what BIOS can do for you,
  251. you just need to read the header comments at the beginning of each section
  252. of the listing.
  253. BIOS services are invoked by means of the INT instruction; the BIOS occu-
  254. pies interrupts 10H through 1FH and also interrupt 5H; actually, of these
  255. seventeen interrupts, five are used for user exit points or data pointers,
  256. leaving twelve actual services.
  257. In most cases, a service deals with a particular hardware interface; for
  258. example, BIOS interrupt 10H deals with the screen.  As with DOS function
  259. calls, many BIOS services can be passed a function code in the AH register
  260. and possible other arguments.
  261. I am not going to summarize the most useful BIOS features here; you will
  262. see some examples in the next sample program we will look at.
  263. The other thing you might want to get into with the Tech reference is the
  264. description of some hardware options, particularly the asynch adapter,
  265. which are not well supported in the BIOS.  The writeup on the asynch adapt-
  266. er is pretty complete.
  267. Actually, the Tech reference itself is pretty complete and very nice as far
  268. as it goes.  One thing which is missing from the Tech reference is informa-
  269. tion on the programmable peripheral chips on the system board.  These
  270. include
  271.       the 8259 interrupt controller
  272.       the 8253 timer
  273.       the 8237 DMA controller and
  274.       the 8255 peripheral interface
  275. To make your library absolutely complete, you should order the INTEL data
  276. sheets for these beasts.
  277. I should say, though, that the only I ever found I needed to know about was
  278. the interrupt controller.  If you happen to have the 8086 Family User's
  279. Manual, the big book put out by INTEL, which is one of the things people
  280. sometimes buy to learn about 8086 architecture, there is an appendix there
  281. which gives an adequate description of the 8259.
  282.  
  283.  
  284. IBM PC Assembly Language Tutorial                                        24
  285.  
  286.  
  287. A final example
  288. _______________
  289. A final example
  290. A final example
  291. A final example
  292. I leave you with a more substantial example of code which illustrates some
  293. good elementary techniques; I won't claim its style is perfect, but I think
  294. it is adequate.  I think this is a much more useful example than what you
  295. will get with the assembler:
  296.           PAGE 61,132
  297.           TITLE SETSCRN -- Establish correct monitor use at boot time
  298. ;
  299. ;         This program is a variation on many which toggle the equipment flags
  300. ;         to support the use of either video option (monochrome or color).
  301. ;         The thing about this one is it prompts the user in such a way that he
  302. ;         can select the use of the monitor he is currently looking at (or which
  303. ;         is currently connected or turned on) without really having to know
  304. ;         which is which.  SETSCRN is a good program to put first in an
  305. ;         AUTOEXEC.BAT file.
  306. ;
  307. ;         This program is highly dependent on the hardware and BIOS of the IBMPC
  308. ;         and is hardly portable, except to very exact clones.  For this reason,
  309. ;         BIOS calls are used in lieu of DOS function calls where both provide
  310. ;         equal function.
  311. ;
  312. OK.  That's the first page of the program.  Notice the PAGE statement,
  313. which you can use to tell the assembler how to format the listing.  You
  314. give it lines per page and characters per line.  I have mine setup to print
  315. on the host lineprinter; I routinely upload my listings at 9600 baud and
  316. print them on the host; it is faster than using the PC printer.
  317. There is also a TITLE statement.  This simply provides a nice title for
  318. each page of your listing.  Now for the second page:
  319.           SUBTTL -- Provide .COM type environment and Data
  320.           PAGE
  321. ;
  322. ;         First, describe the one BIOS byte we are interested in
  323. ;
  324. BIOSDATA  SEGMENT   AT 40H    ;Describe where BIOS keeps his data
  325.           ORG       10H       ;Skip parts we are not interested in
  326. EQUIP     DB        ?         ;Equipment flag location
  327. MONO      EQU       00110000B ;These bits on if monochrome
  328. COLOR     EQU       11101111B ;Mask to make BIOS think of the color board
  329. BIOSDATA  ENDS                ;End of interesting part
  330. ;
  331. ;         Next, describe some values for interrupts and functions
  332. ;
  333. DOS       EQU       21H       ;DOS Function Handler INT code
  334. PRTMSG    EQU       09H       ;Function code to print a message
  335. KBD       EQU       16H       ;BIOS keyboard services INT code
  336. GETKEY    EQU       00H       ;Function code to read a character
  337. SCREEN    EQU       10H       ;BIOS Screen services INT code
  338. MONOINIT  EQU       02H       ;Value to initialize monochrome screen
  339. IBM PC Assembly Language Tutorial                                        25
  340.  
  341.  
  342. ;COLORINIT EQU       03H       ;Value to initialize color screen (80x25)
  343. COLORINIT EQU      01H       ;Value to initialize color screen (40X25)
  344. ;
  345. ;         Now, describe our own segment
  346. ;
  347. SETSCRN   SEGMENT             ;Set operating segment for CODE and DATA
  348. ;
  349.           ASSUME CS:SETSCRN,DS:SETSCRN,ES:SETSCRN,SS:SETSCRN    ;All segments
  350. ;
  351.           ORG       100H      ;Begin assembly at standard .COM offset
  352. ;
  353. MAIN      PROC      NEAR      ;COM files use NEAR linkage
  354.           JMP       BEGIN     ;And, it is helpful to put the data first, but
  355. ;                             ;then you must branch around it.
  356. ;
  357. ;         Data used in SETSCRN
  358. ;
  359. CHANGELOC   DD      EQUIP     ;Location of the EQUIP, recorded as far pointer
  360. MONOPROMPT  DB      'Please press the plus ( + ) key.$'    ;User sees on mono
  361. COLORPROMPT DB      'Please press the minus ( - ) key.$'   ;User sees on color
  362. Several things are illustrated on this page.  First, in addition to titles,
  363. the assembler supports subtitles:  hence the SUBTTL pseudo-op.  Second, the
  364. PAGE pseudo-op can be used to go to a new page in the listing.  You see an
  365. example here of the DSECT-style segment in the "SEGMENT AT 40H".  Here, our
  366. our interest is in correctly describing the location of some data in the
  367. BIOS work area which really is located at segment 40H.
  368. You will also see illustrated the EQU instruction, which just gives a sym-
  369. bolic name to a number.  I don't make a fetish of giving a name to every
  370. single number in a program.  I do feel strongly, though, that interrupts
  371.  
  372.